/**
 * @author yang
 * @date 2018/03/15
 * @description novels util
 */
const axios = require('axios');
const cheerio = require('cheerio')
const iconv = require("iconv-lite");
const novels = [{
    url:'https://m.biquwu.cc',
    base:'m.biquwu.cc',
    query:'/search.php?keyword={q}&page={page}',
    result:{
        container:'.result-item',
        title:'.result-game-item-title-link span',
        desc:'.result-game-item-desc',
        link:'.result-game-item-title-link',
        author:'',
        catalog:'',
        all:'.result-game-item-info',
        allSub:'p'
    },
    novel:{
        chapterItem:'a',
        chapterClass:'.chapter',
        pageClass:'.middle option',
        title:'.block_txt2 h2',
        desc:'.intro_info',
        author:'.block_txt2',
        cover:'.block_img2 img',
        chapter:{
            title:'.nr_title',
            content:'.nr_nr',
            next:'.next a',
            prev:'.prev a'
        }
    }
},{
    url:'https://m.zwdu.com',
    base:'m.zwdu.com',
    query:'/search.php?keyword={q}&page={page}',
    result:{
        container:'.result-item',
        title:'.result-game-item-title-link span',
        desc:'.result-game-item-desc',
        link:'.result-game-item-title-link',
        author:'',
        catalog:'',
        all:'.result-game-item-info',
        allSub:'p'
    },
    novel:{
        chapterItem:'a',
        chapterClass:'.chapter',
        pageClass:'.middle option',
        title:'.block_txt2 h2',
        desc:'.intro_info',
        author:'.block_txt2',
        cover:'.block_img2 img',
        chapter:{
            title:'.nr_title',
            content:'.nr_nr',
            next:'.next a',
            prev:'.prev a'
        }
    }
}]

/**
 * @param string q
 * @param number page
 * @returns {Promise.<*[]>}
 */
function query(q,page) {
    let res = []
    novels.forEach(siteItem => {
        let queryurl = `${siteItem.url}${siteItem.query}`.replace('{q}',encodeURI(q)).replace('{page}',page);
        res.push(new Promise((resolve,reject) =>{
            parseUrl(queryurl).then( $ =>{
                const results = [];
                const handleResult  = siteItem.result;
                $(handleResult.container).each((i,e) =>{
                    let obj = {
                        title:'',
                        all:[],
                        author:'',
                        catalog:'',
                        desc:'',
                        link:'',
                    }
                    obj.link = $(e).find(handleResult.link).attr('href');
                    if(obj.link.indexOf(siteItem.base)<0){
                        obj.link = siteItem.url + obj.link;
                    }
                    if(handleResult.all){
                        $(e).find(handleResult.all).find(handleResult.allSub).each((ind,ele)=>{
                            obj.all.push($(ele).text().replace(/\n/g,'').replace(/\s/g,''));
                        })
                    }
                    for(let key in obj){
                        if(key!='link'&&key!='all'){
                            if(handleResult[key]){
                                obj[key] = $(e).find(handleResult[key]).text();
                            }
                        }
                    }
                    results.push(obj);
                });
                resolve(results)
            }).catch(error =>{
                reject(error);
            })
        }))
    })
    return Promise.all(res);
}

/**
 *
 * @param url
 * @param page
 * @returns {Promise.<{pages: Array, chapters: Array}>}
 */
async function novel(url) {
    const model = getNovel(url);
    const novel = model.novel;
    const obj = {
        title:'',
        author:'',
        desc:'',
        cover:'',
        chapters:[],
        pages:[]
    }
    await parseUrl(url).then($ => {
        obj.title =$(novel.title).text().trim();
        obj.cover =$(novel.cover).attr('src');
        obj.desc =$(novel.desc).text().trim();
        obj.author =$(novel.author).text().trim();
        $(novel.chapterClass).last().find(novel.chapterItem).each((i,e)=>{
            let url  =$(e).attr('href');
            if( url.indexOf(model.base)<0){
                url = model.url+url;
            }
            obj.chapters.push({url,name:$(e).text().trim()})
        })
        if(novel.pageClass){
            $(novel.pageClass).each((i,e)=>{
                let url  =$(e).attr('href')||$(e).attr('value');
                if( url.indexOf(model.base)<0){
                    url = model.url+url;
                }
                obj.pages.push({url,name:$(e).text().trim()})
            })
        }
    })
    return obj;
}

/**
 * @param url
 * @returns {*}
 */
function getNovel(url) {
    return novels.filter(a => url.indexOf(a.base)>0)[0];
}
/**
 * @param url
 * @param encoding
 */
async function parseUrl(url) {
    let $ = null;
    await axios.get(url,{responseType:'arraybuffer'}).then(resp =>{
        const data = resp.data;
        const buf = new Buffer(data,'binary')
        $  = cheerio.load(iconv.decode(buf,'utf-8'),{decodeEntities: false});
        let charset = $('meta').first().attr('charset');
        if(charset.toLowerCase() !='utf-8'){
            $  = cheerio.load(iconv.decode(buf,charset),{decodeEntities: false});
        }
    })
    return $;
}

/**
 * @param url
 * @returns {Promise.<{title: string, content: string, prev: string, next: string}>}
 */
async function chapter(url) {
    const model = getNovel(url);
    const chapter = model.novel.chapter;
    const obj = {
        title:'',
        content:'',
        prev:'',
        next:''}
    await parseUrl(url).then($=>{
        obj.title = $(chapter.title).text().trim();
        obj.content = $(chapter.content).html();
        obj.prev = $(chapter.prev).attr('href');
        obj.next = $(chapter.next).attr('href');
        if(obj.prev.indexOf(model.base)<0){
            obj.prev = model.url + obj.prev;
            obj.next = model.url + obj.next;
        }
    })
    return obj;
}

module.exports = {
    query,
    novel,
    chapter
}